<template>
  <div :class="classes">
    <slot></slot>
  </div>
</template>
<script>

import { oneOf } from '../../utils/util'

const prefixCls = 'bin-steps'

function debounce(fn) {
  let waiting
  return function () {
    if (waiting) return
    waiting = true
    const context = this
    const args = arguments
    const later = function () {
      waiting = false
      fn.apply(context, args)
    }
    this.$nextTick(later)
  }
}

export default {
  name: 'BSteps',
  props: {
    current: {
      type: Number,
      default: 0
    },
    status: {
      validator(value) {
        return oneOf(value, ['wait', 'process', 'finish', 'error', 'success'])
      },
      default: 'process'
    },
    size: {
      validator(value) {
        return oneOf(value, ['small'])
      }
    },
    direction: {
      validator(value) {
        return oneOf(value, ['horizontal', 'vertical'])
      },
      default: 'horizontal'
    }
  },
  computed: {
    classes() {
      return [
        `${prefixCls}`,
        `${prefixCls}-${this.direction}`,
        {
          [`${prefixCls}-${this.size}`]: !!this.size
        }
      ]
    }
  },
  methods: {
    updateChildProps(isInit) {
      const total = this.$children.length
      this.$children.forEach((child, index) => {
        child.stepNumber = index + 1

        if (this.direction === 'horizontal') {
          child.total = total
        }
        // 如果已存在status,且在初始化时,则略过
        // todo 如果当前是error,在current改变时需要处理
        if (!(isInit && child.currentStatus)) {
          if (index === this.current) {
            if (this.status !== 'error') {
              child.currentStatus = 'process'
            }
            if (this.status === 'success') {
              child.currentStatus = 'success'
            }
          } else if (index < this.current) {
            child.currentStatus = 'finish'
          } else {
            child.currentStatus = 'wait'
          }
        }

        if (child.currentStatus !== 'error' && index !== 0) {
          this.$children[index - 1].nextError = false
        }
      })
    },
    setNextError() {
      this.$children.forEach((child, index) => {
        if (child.currentStatus === 'error' && index !== 0) {
          this.$children[index - 1].nextError = true
        }
      })
    },
    updateCurrent(isInit) {
      // 防止溢出边界
      if (this.current < 0 || this.current >= this.$children.length) {
        return
      }
      if (isInit) {
        if (!this.$children[this.current].currentStatus) {
          this.$children[this.current].currentStatus = this.status
        }
      } else {
        this.$children[this.current].currentStatus = this.status
      }
    },
    debouncedAppendRemove() {
      return debounce(function () {
        this.updateSteps()
      })
    },
    updateSteps() {
      this.updateChildProps(true)
      this.setNextError()
      this.updateCurrent(true)
    }
  },
  mounted() {
    this.updateSteps()
    this.$on('append', this.debouncedAppendRemove())
    this.$on('remove', this.debouncedAppendRemove())
  },
  watch: {
    current() {
      this.updateChildProps()
    },
    status() {
      this.updateCurrent()
    }
  }
}
</script>
